home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 676-700 / 681 / term / source.lha / Serial.c < prev    next >
C/C++ Source or Header  |  1992-05-09  |  18KB  |  981 lines

  1. /*
  2. **    $Id: Serial.c,v 1.4 92/04/21 16:59:38 olsen Sta Locker: olsen $
  3. **    $Revision: 1.4 $
  4. **    $Date: 92/04/21 16:59:38 $
  5. **
  6. **    Serial driver support routines
  7. **
  8. **    Copyright © 1990-1992 by Olaf `Olsen' Barthel & MXM
  9. **        All Rights Reserved
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14.     /* Include the OwnDevUnit definitions. */
  15.  
  16. #include "OwnDevUnit.h"
  17.  
  18.     /* Local copy of serial driver name and unit number. */
  19.  
  20. STATIC UBYTE    SerialDevice[40];
  21. STATIC LONG    UnitNumber = -1;
  22.  
  23.     /* XOn():
  24.      *
  25.      *    Perform XON (stop data flow).
  26.      */
  27.  
  28. VOID
  29. XOn()
  30. {
  31.     if(Config . Handshaking == HANDSHAKING_XONXOFF)
  32.         Status = STATUS_HOLDING;
  33. }
  34.  
  35.     /* SetFlags(struct IOExtSer *SomeRequest):
  36.      *
  37.      *    Set the contents of a serial device request according
  38.      *    to the current configuration settings.
  39.      */
  40.  
  41. VOID __regargs
  42. SetFlags(struct IOExtSer *SomeRequest)
  43. {
  44.     SomeRequest -> io_Baud        = Config . BaudRate;
  45.     SomeRequest -> io_BrkTime    = Config . BreakLength;
  46.     SomeRequest -> io_ReadLen    = Config . BitsPerChar;
  47.     SomeRequest -> io_WriteLen    = Config . BitsPerChar;
  48.     SomeRequest -> io_StopBits    = Config . StopBits;
  49.  
  50.     SomeRequest -> io_ExtFlags    &= ~(SEXTF_MSPON|SEXTF_MARK);
  51.     SomeRequest -> io_SerFlags    &= ~(SERF_PARTY_ON|SERF_PARTY_ODD|SERF_7WIRE|SERF_RAD_BOOGIE);
  52.  
  53.     switch(Config . Parity)
  54.     {
  55.         case PARITY_EVEN:    SomeRequest -> io_SerFlags |= SERF_PARTY_ON;
  56.                     break;
  57.  
  58.         case PARITY_ODD:    SomeRequest -> io_SerFlags |= SERF_PARTY_ON|SERF_PARTY_ODD;
  59.                     break;
  60.  
  61.         case PARITY_MARK:    SomeRequest -> io_SerFlags |= SERF_PARTY_ON;
  62.                     SomeRequest -> io_ExtFlags |= SEXTF_MSPON|SEXTF_MARK;
  63.                     break;
  64.  
  65.         case PARITY_SPACE:    SomeRequest -> io_SerFlags |= SERF_PARTY_ON;
  66.                     SomeRequest -> io_ExtFlags |= SEXTF_MSPON;
  67.                     break;
  68.  
  69.         default:        break;
  70.     }
  71.  
  72.     if(Config . Handshaking == HANDSHAKING_RTSCTS || Config . Handshaking == HANDSHAKING_RTSCTS_DSR)
  73.         SomeRequest -> io_SerFlags |= SERF_7WIRE;
  74.  
  75.     if(Config . HighSpeed & ~SERIAL_SHARED)
  76.         SomeRequest -> io_SerFlags |= SERF_RAD_BOOGIE;
  77.  
  78.     if(Config . HighSpeed & SERIAL_SHARED)
  79.         SomeRequest -> io_SerFlags |= SERF_SHARED;
  80.  
  81.     SomeRequest -> io_SerFlags |= SERF_XDISABLED;
  82. }
  83.  
  84.     /* CallMenu(UBYTE *Name,ULONG Code):
  85.      *
  86.      *    Call a menu function either through the name of the corresponding
  87.      *    menu item or a menu number.
  88.      */
  89.  
  90. STATIC VOID __regargs
  91. CallMenu(UBYTE *Name,ULONG Code)
  92. {
  93.     WORD MenuNum = -1,Item = 0,Sub = 0,i;
  94.  
  95.         /* Are we to look for a name? */
  96.  
  97.     if(Name)
  98.     {
  99.         WORD Len = strlen(Name);
  100.  
  101.             /* Scan the menu list... */
  102.  
  103.         for(i = 0 ; TermMenu[i] . nm_Type != NM_END ; i++)
  104.         {
  105.             switch(TermMenu[i] . nm_Type)
  106.             {
  107.                 case NM_TITLE:    MenuNum++;
  108.                         Item = Sub = 0;
  109.                         break;
  110.  
  111.                 case NM_ITEM:    Sub = 0;
  112.                         break;
  113.             }
  114.  
  115.                 /* Did we get a valid name string? */
  116.  
  117.             if(TermMenu[i] . nm_Label != NM_BARLABEL)
  118.             {
  119.                     /* Does the name match our template? */
  120.  
  121.                 if(!Strnicmp(TermMenu[i] . nm_Label,Name,Len))
  122.                 {
  123.                     struct MenuItem *MenuItem = ItemAddress(Menu,FULLMENUNUM(MenuNum,Item,Sub));
  124.  
  125.                     if(MenuItem)
  126.                         HandleCode((ULONG)TermMenu[i] . nm_UserData,NULL,MenuItem);
  127.  
  128.                     break;
  129.                 }
  130.             }
  131.  
  132.             switch(TermMenu[i] . nm_Type)
  133.             {
  134.                 case NM_ITEM:    Item++;
  135.                         break;
  136.  
  137.                 case NM_SUB:    Sub++;
  138.                         break;
  139.             }
  140.         }
  141.     }
  142.     else
  143.     {
  144.         WORD    TheMenu    =  Code % 100,
  145.             TheItem    = (Code / 100) % 100,
  146.             TheSub    =  Code / 10000;
  147.  
  148.             /* Scan the menu list... */
  149.  
  150.         for(i = 0 ; TermMenu[i] . nm_Type != NM_END ; i++)
  151.         {
  152.             switch(TermMenu[i] . nm_Type)
  153.             {
  154.                 case NM_TITLE:    MenuNum++;
  155.                         Item = Sub = 0;
  156.                         break;
  157.  
  158.                 case NM_ITEM:    Sub = 0;
  159.                         break;
  160.             }
  161.  
  162.                 /* Is it the menu number we want? */
  163.  
  164.             if(TheMenu == MenuNum && TheItem == Item && TheSub == Sub)
  165.             {
  166.                 if(TermMenu[i] . nm_Label != NM_BARLABEL)
  167.                 {
  168.                     struct MenuItem *MenuItem = ItemAddress(Menu,FULLMENUNUM(MenuNum,Item,Sub));
  169.  
  170.                     if(MenuItem)
  171.                         HandleCode((ULONG)TermMenu[i] . nm_UserData,NULL,MenuItem);
  172.                 }
  173.  
  174.                 break;
  175.             }
  176.  
  177.             switch(TermMenu[i] . nm_Type)
  178.             {
  179.                 case NM_ITEM:    Item++;
  180.                         break;
  181.  
  182.                 case NM_SUB:    Sub++;
  183.                         break;
  184.             }
  185.         }
  186.     }
  187. }
  188.  
  189.     /* SerialCommand(UBYTE *String):
  190.      *
  191.      *    Send a command string to the serial line and
  192.      *    interprete the control sequences.
  193.      */
  194.  
  195. VOID __regargs
  196. SerialCommand(UBYTE *String)
  197. {
  198.     LONG    Count = 0,i,Len = strlen(String);
  199.  
  200.     BYTE    GotControl    = FALSE,
  201.         GotEscape    = FALSE,
  202.  
  203.         OldStatus,
  204.         BlockSet;
  205.  
  206.         /* Scan the string. */
  207.  
  208.     for(i = 0 ; i < Len ; i++)
  209.     {
  210.             /* We are looking for plain characters
  211.              * and the control ('\') and escape
  212.              * ('^') characters.
  213.              */
  214.  
  215.         if(!GotControl && !GotEscape)
  216.         {
  217.                 /* Got a control character,
  218.                  * the next byte will probably be
  219.                  * a command sequence.
  220.                  */
  221.  
  222.             if(String[i] == '\\')
  223.             {
  224.                 GotControl = TRUE;
  225.                 continue;
  226.             }
  227.  
  228.                 /* Got an escape character,
  229.                  * the next byte will be some
  230.                  * kind of control character
  231.                  * (such as XON, XOF, bell, etc.).
  232.                  */
  233.  
  234.             if(String[i] == '^')
  235.             {
  236.                 GotEscape = TRUE;
  237.                 continue;
  238.             }
  239.  
  240.                 /* This tells us to wait another
  241.                  * second before continuing with
  242.                  * the scanning.
  243.                  */
  244.  
  245.             if(String[i] == '~')
  246.             {
  247.                 if(Count)
  248.                 {
  249.                     SerWrite(SharedBuffer,Count);
  250.  
  251.                     Count = 0;
  252.                 }
  253.  
  254.                 WaitTime(0,MILLION / 2);
  255.                 HandleSerial();
  256.  
  257.                 continue;
  258.             }
  259.  
  260.                 /* Stuff the character into the
  261.                  * buffer.
  262.                  */
  263.  
  264.             SharedBuffer[Count++] = String[i];
  265.         }
  266.         else
  267.         {
  268.                 /* Convert the character to a control
  269.                  * style character (^C, etc.).
  270.                  */
  271.  
  272.             if(GotEscape)
  273.             {
  274.                 if(ToUpper(String[i]) >= 'A' && ToUpper(String[i]) <= 91)
  275.                     SharedBuffer[Count++] = ToUpper(String[i]) - '@';
  276.                 else
  277.                     SharedBuffer[Count++] = String[i];
  278.  
  279.                 GotEscape = FALSE;
  280.             }
  281.  
  282.                 /* The next character represents a command. */
  283.  
  284.             if(GotControl)
  285.             {
  286.                 switch(ToUpper(String[i]))
  287.                 {
  288.                         /* Execute an AmigaDOS command. */
  289.  
  290.                     case 'D':    if(!WeAreBlocking)
  291.                             {
  292.                                 BlockSet = TRUE;
  293.  
  294.                                 BlockWindows();
  295.                             }
  296.                             else
  297.                                 BlockSet = FALSE;
  298.  
  299.                             SendAmigaDOSCommand(&String[i + 1]);
  300.  
  301.                             if(BlockSet)
  302.                                 ReleaseWindows();
  303.  
  304.                             return;
  305.  
  306.                         /* Execute an ARexx command. */
  307.  
  308.                     case 'A':    if(!WeAreBlocking)
  309.                             {
  310.                                 BlockSet = TRUE;
  311.  
  312.                                 BlockWindows();
  313.                             }
  314.                             else
  315.                                 BlockSet = FALSE;
  316.  
  317.                             SendARexxCommand(&String[i + 1]);
  318.  
  319.                             if(BlockSet)
  320.                                 ReleaseWindows();
  321.  
  322.                             return;
  323.  
  324.                         /* Add the control character ('\'). */
  325.  
  326.                     case '\\':    SharedBuffer[Count++] = '\\';
  327.                             break;
  328.  
  329.                         /* This is a backspace. */
  330.  
  331.                     case 'B':    SharedBuffer[Count++] = '\b';
  332.                             break;
  333.  
  334.                         /* This is a form feed. */
  335.  
  336.                     case 'F':    SharedBuffer[Count++] = '\f';
  337.                             break;
  338.  
  339.                         /* This is a line feed. */
  340.  
  341.                     case 'N':    SharedBuffer[Count++] = '\n';
  342.                             break;
  343.  
  344.                         /* Send the current password. */
  345.  
  346.                     case 'P':    if(Password[0])
  347.                             {
  348.                                 if(Count)
  349.                                 {
  350.                                     SerWrite(SharedBuffer,Count);
  351.  
  352.                                     Count = 0;
  353.                                 }
  354.  
  355.                                 SerWrite(Password,strlen(Password));
  356.                             }
  357.  
  358.                             break;
  359.  
  360.                         /* This is a carriage return. */
  361.  
  362.                     case 'R':    SharedBuffer[Count++] = '\r';
  363.                             break;
  364.  
  365.                         /* This is a tab. */
  366.  
  367.                     case 'T':    SharedBuffer[Count++] = '\t';
  368.                             break;
  369.  
  370.                         /* Send the current user name. */
  371.  
  372.                     case 'U':    if(UserName[0])
  373.                             {
  374.                                 if(Count)
  375.                                 {
  376.                                     SerWrite(SharedBuffer,Count);
  377.  
  378.                                     Count = 0;
  379.                                 }
  380.  
  381.                                 SerWrite(UserName,strlen(UserName));
  382.                             }
  383.  
  384.                             break;
  385.  
  386.                         /* Send a break across the serial line. */
  387.  
  388.                     case 'X':    if(Count)
  389.                             {
  390.                                 SerWrite(SharedBuffer,Count);
  391.  
  392.                                 Count = 0;
  393.                             }
  394.  
  395.                             if(WriteRequest)
  396.                             {
  397.                                 OldStatus = Status;
  398.  
  399.                                 Status = STATUS_BREAKING;
  400.  
  401.                                 WriteRequest -> IOSer . io_Command = SDCMD_BREAK;
  402.  
  403.                                 DoIO(WriteRequest);
  404.  
  405.                                 Status = OldStatus;
  406.                             }
  407.  
  408.                             break;
  409.  
  410.                         /* Feed the contents of the
  411.                          * clipboard into the input
  412.                          * stream.
  413.                          */
  414.  
  415.                     case 'I':    if(Count)
  416.                                 SerWrite(SharedBuffer,Count);
  417.  
  418.                             Count = LoadClip(SharedBuffer,256);
  419.  
  420.                             break;
  421.  
  422.                         /* Send a string to the clipboard. */
  423.  
  424.                     case 'G':    if(String[i + 1])
  425.                                 SaveClip(&String[i + 1],strlen(&String[i + 1]));
  426.  
  427.                             return;
  428.  
  429.                         /* Produce the escape character. */
  430.  
  431.                     case 'E':    SharedBuffer[Count++] = ESC;
  432.                             break;
  433.  
  434.                         /* Call a menu item. */
  435.  
  436.                     case 'C':    i++;
  437.  
  438.                                 /* Scan for a menu number or
  439.                                  * a single quote...
  440.                                  */
  441.  
  442.                             while(i < Len)
  443.                             {
  444.                                 if(String[i] >= '0' && String[i] <= '9')
  445.                                     break;
  446.  
  447.                                 if(String[i] == '\'')
  448.                                     break;
  449.  
  450.                                 if(String[i] != ' ')
  451.                                     break;
  452.  
  453.                                 i++;
  454.                             }
  455.  
  456.                             if(i < Len)
  457.                             {
  458.                                 UBYTE DummyBuffer[256];
  459.  
  460.                                     /* Did we get a quote? */
  461.  
  462.                                 if(String[i] == '\'')
  463.                                 {
  464.                                     LONG Start = ++i;
  465.  
  466.                                     if(String[Start])
  467.                                     {
  468.                                         WORD Length;
  469.  
  470.                                         while(i < Len)
  471.                                         {
  472.                                             if(String[i] != '\'')
  473.                                                 i++;
  474.                                             else
  475.                                                 break;
  476.                                         }
  477.  
  478.                                         if(String[i] == '\'')
  479.                                             Length = i - Start;
  480.                                         else
  481.                                             Length = i - Start + 1;
  482.  
  483.                                         memcpy(DummyBuffer,&String[Start],Length);
  484.  
  485.                                         DummyBuffer[Length] = 0;
  486.  
  487.                                         CallMenu(DummyBuffer,0);
  488.                                     }
  489.                                 }
  490.                                 else
  491.                                 {
  492.                                     if(String[i] >= '0' && String[i] <= '9')
  493.                                     {
  494.                                         LONG Start = i,Length;
  495.  
  496.                                         while(i < Len)
  497.                                         {
  498.                                             if(String[i] >= '0' && String[i] <= '9')
  499.                                                 i++;
  500.                                             else
  501.                                                 break;
  502.                                         }
  503.  
  504.                                         if(i == Start)
  505.                                             Length = 1;
  506.                                         else
  507.                                             Length = i - Start;
  508.  
  509.                                         memcpy(DummyBuffer,&String[Start],Length);
  510.  
  511.                                         DummyBuffer[Length] = 0;
  512.  
  513.                                         CallMenu(NULL,atol(DummyBuffer));
  514.                                     }
  515.                                 }
  516.                             }
  517.  
  518.                             break;
  519.  
  520.                         /* Stuff the character into the buffer. */
  521.  
  522.                     default:    SharedBuffer[Count++] = String[i];
  523.                             break;
  524.                 }
  525.  
  526.                 GotControl = FALSE;
  527.             }
  528.         }
  529.  
  530.             /* If the buffer is full, release it. */
  531.  
  532.         if(Count == 256)
  533.         {
  534.             SerWrite(SharedBuffer,Count);
  535.  
  536.             Count = 0;
  537.         }
  538.     }
  539.  
  540.     if(Count)
  541.         SerWrite(SharedBuffer,Count);
  542. }
  543.  
  544.     /* SerWrite(APTR Buffer,LONG Size):
  545.      *
  546.      *    Send a number of bytes across the serial line.
  547.      */
  548.  
  549. VOID __regargs
  550. SerWrite(APTR Buffer,LONG Size)
  551. {
  552.     if(WriteRequest && Size)
  553.     {
  554.         if(XProtocolBase)
  555.         {
  556.                 /* xpr wants to see the data before it is
  557.                  * transferred.
  558.                  */
  559.  
  560.             if(TransferBits & XPRS_USERMON)
  561.             {
  562.                 if(!(Size = XProtocolUserMon(XprIO,Buffer,Size,Size)))
  563.                     return;
  564.             }
  565.         }
  566.  
  567.             /* If full duplex is enabled, send the entire
  568.              * buffer.
  569.              */
  570.  
  571.         if(Config . Duplex == DUPLEX_FULL)
  572.         {
  573.             WriteRequest -> IOSer . io_Command    = CMD_WRITE;
  574.             WriteRequest -> IOSer . io_Data        = Buffer;
  575.             WriteRequest -> IOSer . io_Length    = Size;
  576.  
  577.             DoIO(WriteRequest);
  578.         }
  579.         else
  580.         {
  581.             if(XEmulatorBase)
  582.             {
  583.                 WriteRequest -> IOSer . io_Command    = CMD_WRITE;
  584.                 WriteRequest -> IOSer . io_Data        = Buffer;
  585.                 WriteRequest -> IOSer . io_Length    = Size;
  586.  
  587.                 SendIO(WriteRequest);
  588.  
  589.                 ConProcess(Buffer,Size);
  590.  
  591.                 WaitIO(WriteRequest);
  592.             }
  593.             else
  594.             {
  595.                 UBYTE *ByteBuffer = Buffer;
  596.  
  597.                     /* Half duplex is enabled, send only
  598.                      * a single character at a time.
  599.                      */
  600.  
  601.                 while(Size--)
  602.                 {
  603.                     WriteRequest -> IOSer . io_Command    = CMD_WRITE;
  604.                     WriteRequest -> IOSer . io_Length    = 1;
  605.                     WriteRequest -> IOSer . io_Data        = ByteBuffer;
  606.  
  607.                     SendIO(WriteRequest);
  608.  
  609.                     ConProcess(ByteBuffer,1);
  610.  
  611.                     WaitIO(WriteRequest);
  612.  
  613.                     ByteBuffer++;
  614.                 }
  615.             }
  616.         }
  617.     }
  618. }
  619.  
  620.     /* ClearSerial():
  621.      *
  622.      *    Terminate all read/write activity on the serial
  623.      *    line.
  624.      */
  625.  
  626. VOID
  627. ClearSerial()
  628. {
  629.     if(ReadRequest)
  630.     {
  631.         if(!CheckIO(ReadRequest))
  632.             AbortIO(ReadRequest);
  633.  
  634.         WaitIO(ReadRequest);
  635.     }
  636.  
  637.     if(WriteRequest)
  638.     {
  639.         WriteRequest -> IOSer . io_Command = CMD_CLEAR;
  640.  
  641.         DoIO(WriteRequest);
  642.     }
  643. }
  644.  
  645.     /* DropDTR():
  646.      *
  647.      *    Drop the data terminal ready signal (i.e. close, wait a bit
  648.      *    and then reopen the serial drive).
  649.      */
  650.  
  651. BYTE
  652. DropDTR()
  653. {
  654.         /* Finish all serial read activity. */
  655.  
  656.     ClearSerial();
  657.  
  658.         /* Do we have any channels to work with? */
  659.  
  660.     if(ReadRequest && WriteRequest)
  661.     {
  662.             /* Close the device. */
  663.  
  664.         CloseDevice(ReadRequest);
  665.  
  666.             /* Wait a bit. */
  667.  
  668.         WaitTime(1,0);
  669.  
  670.             /* Set up the original configuration data. */
  671.  
  672.         SetFlags(ReadRequest);
  673.  
  674.         ReadRequest -> io_RBufLen = Config . SerBuffSize;
  675.  
  676.             /* Reopen the driver. */
  677.  
  678.         if(!OpenDevice(Config . SerialDevice,Config . UnitNumber,ReadRequest,0))
  679.         {
  680.             struct MsgPort *WritePort = WriteRequest -> IOSer . io_Message . mn_ReplyPort;
  681.  
  682.                 /* Fill in the rest. */
  683.  
  684.             CopyMem(ReadRequest,WriteRequest,sizeof(struct IOExtSer));
  685.  
  686.             WriteRequest -> IOSer . io_Message . mn_ReplyPort = WritePort;
  687.  
  688.             WriteRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  689.  
  690.             SetFlags(WriteRequest);
  691.  
  692.             DoIO(WriteRequest);
  693.  
  694.                 /* Restart read activity. */
  695.  
  696.             ReadRequest -> IOSer . io_Command    = CMD_READ;
  697.             ReadRequest -> IOSer . io_Data        = ReadBuffer;
  698.             ReadRequest -> IOSer . io_Length    = 1;
  699.  
  700.             SetSignal(0,SIG_SERIAL);
  701.  
  702.             SendIO(ReadRequest);
  703.  
  704.             return(TRUE);
  705.         }
  706.         else
  707.             DeleteSerial();
  708.     }
  709.     else
  710.     {
  711.         DeleteSerial();
  712.  
  713.         return(TRUE);
  714.     }
  715.  
  716.     return(FALSE);
  717. }
  718.  
  719.     /* DeleteSerial():
  720.      *
  721.      *    Close the serial device and release all associated
  722.      *    resources.
  723.      */
  724.  
  725. VOID
  726. DeleteSerial()
  727. {
  728.     BYTE Closed = FALSE;
  729.  
  730.     if(ReadRequest)
  731.     {
  732.         if(ReadRequest -> IOSer . io_Device)
  733.         {
  734.             if(!(Config . HighSpeed & SERIAL_SHARED))
  735.             {
  736.                 ReadRequest -> IOSer . io_Command = CMD_RESET;
  737.  
  738.                 DoIO(ReadRequest);
  739.             }
  740.  
  741.             CloseDevice(ReadRequest);
  742.  
  743.             Closed = TRUE;
  744.         }
  745.  
  746.         DeleteIORequest(ReadRequest);
  747.  
  748.         ReadRequest = NULL;
  749.     }
  750.  
  751.     if(WriteRequest)
  752.     {
  753.         if(WriteRequest -> IOSer . io_Device && !Closed)
  754.         {
  755.             if(!(Config . HighSpeed & SERIAL_SHARED))
  756.             {
  757.                 ReadRequest -> IOSer . io_Command = CMD_RESET;
  758.  
  759.                 DoIO(ReadRequest);
  760.             }
  761.  
  762.             CloseDevice(WriteRequest);
  763.         }
  764.  
  765.         if(WriteRequest -> IOSer . io_Message . mn_ReplyPort)
  766.             DeleteMsgPort(WriteRequest -> IOSer . io_Message . mn_ReplyPort);
  767.  
  768.         DeleteIORequest(WriteRequest);
  769.  
  770.         WriteRequest = NULL;
  771.     }
  772.  
  773.     if(ReadPort)
  774.     {
  775.         DeleteMsgPort(ReadPort);
  776.  
  777.         ReadPort = NULL;
  778.     }
  779.  
  780.     if(ReadBuffer)
  781.     {
  782.         FreeVec(ReadBuffer);
  783.  
  784.         ReadBuffer = NULL;
  785.     }
  786.  
  787.     if(HostReadBuffer)
  788.     {
  789.         FreeVec(HostReadBuffer);
  790.  
  791.         HostReadBuffer = NULL;
  792.     }
  793.  
  794.     if(OwnDevUnitBase && SerialDevice[0] && UnitNumber != -1)
  795.     {
  796.         FreeDevUnit(SerialDevice,UnitNumber);
  797.  
  798.         SerialDevice[0] = 0;
  799.  
  800.         UnitNumber = -1;
  801.     }
  802. }
  803.  
  804.     /* CreateSerial():
  805.      *
  806.      *    Create handles for the serial device and open it.
  807.      */
  808.  
  809. UBYTE *
  810. CreateSerial()
  811. {
  812.     struct MsgPort *WritePort;
  813.  
  814.         /* If OwnDevUnit.library is available, try to lock
  815.          * the serial driver.
  816.          */
  817.  
  818. Start:    if(OwnDevUnitBase)
  819.     {
  820.         UBYTE *Error;
  821.  
  822.             /* Attempt to lock the device unit... */
  823.  
  824.         if(Error = AttemptDevUnit(Config . SerialDevice,Config . UnitNumber,TermIDString,NULL))
  825.         {
  826.                 /* Check for error type if any. */
  827.  
  828.             if(!Strnicmp(Error,ODUERR_LEADCHAR,1))
  829.                 SPrintf(SharedBuffer,LocaleString(MSG_SERIAL_ERROR_ACCESSING_TXT),Config . SerialDevice,Config . UnitNumber,&Error[1]);
  830.             else
  831.                 SPrintf(SharedBuffer,LocaleString(MSG_SERIAL_DEVICE_IN_USE_TXT),Config . SerialDevice,Config . UnitNumber,Error);
  832.  
  833.             SerialDevice[0] = 0;
  834.  
  835.             UnitNumber = -1;
  836.  
  837.             return(SharedBuffer);
  838.         }
  839.         else
  840.         {
  841.             strcpy(SerialDevice,Config . SerialDevice);
  842.  
  843.             UnitNumber = Config . UnitNumber;
  844.         }
  845.     }
  846.  
  847.     if(ReadBuffer = AllocVec(Config . SerBuffSize,MEMF_ANY))
  848.     {
  849.         if(XProtocolBase && (TransferBits & XPRS_HOSTNOWAIT))
  850.             HostReadBuffer = AllocVec(Config . SerBuffSize,MEMF_ANY);
  851.         else
  852.             HostReadBuffer = NULL;
  853.  
  854.         if(ReadPort = (struct MsgPort *)CreateMsgPort())
  855.         {
  856.             if(ReadRequest = (struct IOExtSer *)CreateIORequest(ReadPort,sizeof(struct IOExtSer)))
  857.             {
  858.                 SetFlags(ReadRequest);
  859.  
  860.                 ReadRequest -> io_RBufLen = Config . SerBuffSize;
  861.  
  862.                 if(!OpenDevice(Config . SerialDevice,Config . UnitNumber,ReadRequest,0))
  863.                 {
  864.                     if(WritePort = (struct MsgPort *)CreateMsgPort())
  865.                     {
  866.                         if(WriteRequest = (struct IOExtSer *)CreateIORequest(WritePort,sizeof(struct IOExtSer)))
  867.                         {
  868.                             CopyMem(ReadRequest,WriteRequest,sizeof(struct IOExtSer));
  869.  
  870.                             WriteRequest -> IOSer . io_Message . mn_ReplyPort = WritePort;
  871.  
  872.                             WriteRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  873.  
  874.                             SetFlags(WriteRequest);
  875.  
  876.                             DoIO(WriteRequest);
  877.  
  878.                             /* If RTS/CTS (7 wire handshaking) is
  879.                              * selected, have a look at the DSR
  880.                              * line to see whether the modem
  881.                              * connected is willing to support
  882.                              * this handshaking mode.
  883.                              */
  884.  
  885.                             if(Config . Handshaking == HANDSHAKING_RTSCTS_DSR)
  886.                             {
  887. Retry:                                WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  888.  
  889.                                 DoIO(WriteRequest);
  890.  
  891.                                     /* If the line happens to
  892.                                      * be high, there is no
  893.                                      * DSR signal present.
  894.                                      */
  895.  
  896.                                 if(WriteRequest -> io_Status & (1 << 3))
  897.                                 {
  898.                                     if(MyEasyRequest(Window,LocaleString(MSG_SERIAL_NO_DSR_SIGNAL_TXT),LocaleString(MSG_SERIAL_RETRY_CANCEL_TXT)))
  899.                                         goto Retry;
  900.                                     else
  901.                                     {
  902.                                         DeleteSerial();
  903.  
  904.                                         Config . Handshaking = HANDSHAKING_XONXOFF;
  905.  
  906.                                         SerialMessage = LocaleString(MSG_SERIAL_NO_DSR_SIGNAL_HANDSHAKING_DISABLED_TXT);
  907.  
  908.                                         goto Start;
  909.                                     }
  910.                                 }
  911.                             }
  912.  
  913.                             ReadRequest -> IOSer . io_Command    = CMD_READ;
  914.                             ReadRequest -> IOSer . io_Data        = ReadBuffer;
  915.                             ReadRequest -> IOSer . io_Length    = 1;
  916.  
  917.                             SetSignal(0,SIG_SERIAL);
  918.  
  919.                             SendIO(ReadRequest);
  920.  
  921.                             return(NULL);
  922.                         }
  923.                         else
  924.                         {
  925.                             SerialMessage = NULL;
  926.  
  927.                             DeleteSerial();
  928.  
  929.                             return(LocaleString(MSG_SERIAL_NOT_ENOUGH_MEMORY_TXT));
  930.                         }
  931.                     }
  932.                     else
  933.                     {
  934.                         SerialMessage = NULL;
  935.  
  936.                         DeleteSerial();
  937.  
  938.                         return(LocaleString(MSG_SERIAL_FAILED_TO_CREATE_WRITE_PORT_TXT));
  939.                     }
  940.                 }
  941.                 else
  942.                 {
  943.                     ReadRequest -> IOSer . io_Device = NULL;
  944.  
  945.                     DeleteSerial();
  946.  
  947.                     SerialMessage = NULL;
  948.  
  949.                     SPrintf(SharedBuffer,LocaleString(MSG_SERIAL_FAILED_TO_OPEN_UNIT_TXT),Config . SerialDevice,Config . UnitNumber);
  950.  
  951.                     return(SharedBuffer);
  952.                 }
  953.             }
  954.             else
  955.             {
  956.                 SerialMessage = NULL;
  957.  
  958.                 DeleteSerial();
  959.  
  960.                 return(LocaleString(MSG_SERIAL_NOT_ENOUGH_MEMORY_TXT));
  961.             }
  962.         }
  963.         else
  964.         {
  965.             SerialMessage = NULL;
  966.  
  967.             DeleteSerial();
  968.  
  969.             return(LocaleString(MSG_SERIAL_FAILED_TO_CREATE_READ_PORT_TXT));
  970.         }
  971.     }
  972.     else
  973.     {
  974.         SerialMessage = NULL;
  975.  
  976.         DeleteSerial();
  977.  
  978.         return(LocaleString(MSG_SERIAL_NOT_ENOUGH_MEMORY_TXT));
  979.     }
  980. }
  981.